#Calculates various attributes of the Depth of Field of an image, given the supplied settings.

from math import ceil

def calculateDOF (coc, focalLength, focalDist, aperture):

    #Convert focalLength to float, catch invalid input.
    try:
        focalLength = float(focalLength)
    except ValueError:
        return "Invalid Input (focalLength)"
    #Convert focalDist to float, catch invalid input.
    try:
        focalDist = float(focalDist) * 1000
    except ValueError:
        return "Invalid Input (focalDist)"
    #Convert focalDist to float, catch invalid input.
    try:
        aperture = float(aperture)
    except ValueError:
        return "Invalid Input (aperture)"

    #Calculates the hyperfocal distance of the camera in it's current setup
    hyperFocal = (focalLength * focalLength) / (aperture * coc)
    #Calculates the near point (the closest distance at which the image will be in-focus
    nearPoint = (hyperFocal * focalDist) / (hyperFocal + (focalDist - focalLength))
    #Calculates the far point (the farthest distance at which the image will be in-focus
    farPoint = (hyperFocal * focalDist) / (hyperFocal - (focalDist - focalLength))
    #Calculates the actual Depth of Field (the depth of the in-focus portion of the image)
    dof = farPoint - nearPoint

    #Return raw results in millimeters.
    #results = [hyperFocal, nearPoint, farPoint, dof]

    #conversion to meters and formatting for GUI
    dofOutput = ceil(dof) / 1000
    nearPointOutput = ceil(nearPoint) / 1000
    farPointOutput = ceil(farPoint) / 1000

    #preparing results for output to GUI level
    results = "DOF = " + str(dofOutput) + "\nNear Point = " + str(nearPointOutput) + "\nFar Point = " + str(farPointOutput) + " \nall results in meters"

    return results


#Valid Input
#theresults = calculateDOF (0.019948, "50", "3.048", 2.8)
#print theresults
#Invalid input...
#theresults = calculateDOF (0.019948, "zardoz", "3.048", 2.8)
#print theresults
#theresults = calculateDOF (0.019948, "50", "speaks", 2.8)
#print theresults